using Engine;
using Engine.Graphics;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    public class ComponentSteamTurbine : ComponentEngine, IUpdateable, IEngineComponent, IDrawable {
        public UpdateOrder UpdateOrder => UpdateOrder.Default;
        public int[] DrawOrders => [1];
        protected float m_fireTimeRemaining;
        protected float m_heatLevel;
        public float m_speed = 1f;
        public float waterConsumingSpeed = 8 / 300f;
        public float HeatLevel => m_heatLevel;
        public float FireTimeRemaining => m_fireTimeRemaining;

        public SubsystemTerrain m_subsystemTerrain;

        public SubsystemExplosions m_subsystemExplosions;

        public BlockMesh? m_fanMesh;

        public PrimitivesRenderer3D m_primitivesRenderer3D = new();

        public override int GetSlotCapacity(int slotIndex, int value) {
            return BlocksManager.Blocks[Terrain.ExtractContents(value)].GetFuelHeatLevel(value) > 0f ? base.GetSlotCapacity(slotIndex, value) : 0;
        }


        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
            base.Load(valuesDictionary, idToEntityMap);
            m_tanks[0].Capacity = 16;
            m_fireTimeRemaining = valuesDictionary.GetValue("FireTimeRemaining", 0f);
            m_heatLevel = valuesDictionary.GetValue("HeatLevel", 0f);
            m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
            m_subsystemExplosions = Project.FindSubsystem<SubsystemExplosions>(true);

            m_fanMesh = DevicesBlockManager.GetDevice<SteamTurbineDevice>()?.m_fanMesh;
        }

        public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap) {
            base.Save(valuesDictionary, entityToIdMap);
            valuesDictionary.SetValue("FireTimeRemaining", m_fireTimeRemaining);
            valuesDictionary.SetValue("HeatLevel", m_heatLevel);
        }

        public void Update(float dt) {
            if (m_fireTimeRemaining <= 0f) //没有燃烧时间了
            {
                if (m_heatLevel > 0) m_heatLevel = 0; //无燃烧时间，燃料等级归零

                if (GetSlotCount(0) > 0) //燃料添加逻辑
                {
                    int value = GetSlotValue(0);
                    Block block = BlocksManager.Blocks[Terrain.ExtractContents(value)];
                    if (block.GetExplosionPressure(value) > 0f && HasWater()) {
                        m_slots[0].Count--;
                        m_subsystemExplosions.TryExplodeBlock(m_componentBlockEntity.Coordinates.X, m_componentBlockEntity.Coordinates.Y, m_componentBlockEntity.Coordinates.Z, value);
                    }
                    if (block.GetFuelFireDuration(value) > 0
                        && HasWater()) //放入的是正确的燃料，并且水量大于0
                    {
                        m_fireTimeRemaining = block.GetFuelFireDuration(value) * 1.5f;
                        m_heatLevel = block.GetFuelHeatLevel(value);
                        m_slots[0].Count--;
                    }
                }
            }
            else //有燃烧时间
            {
                if (HasWater()) //水量大于0，执行蒸汽机逻辑
                {
                    m_fireTimeRemaining = MathUtils.Max(0, m_fireTimeRemaining - dt);
                    m_tanks[0].Volume = MathUtils.Max(0, m_tanks[0].Volume - dt * waterConsumingSpeed);
                }
                else {
                    m_fireTimeRemaining = 0;
                }
            }
            ReplaceFurnace(m_componentBlockEntity.Coordinates);
        }

        public virtual void ReplaceFurnace(Point3 coordinates) {
            TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(coordinates.X, coordinates.Z);
            if (chunkAtCell != null
                && chunkAtCell.State == TerrainChunkState.Valid) {
                int cellValue = m_subsystemTerrain.Terrain.GetCellValue(coordinates.X, coordinates.Y, coordinates.Z);
                int direction = IlluminableDevice.GetDirection_Static(cellValue);
                int deviceValue = DevicesBlockManager.GetDeviceValueByType(typeof(SteamTurbineDevice), m_heatLevel > 0 ? 0b100 | direction : direction);
                m_subsystemTerrain.ChangeCell(coordinates.X, coordinates.Y, coordinates.Z, deviceValue);
            }
        }

        bool HasWater() => GetTankValue(0) == FluidsManager.GetFluidID("WaterFluid", 0) && GetTankVolume(0) > 0;

        public new bool IsPowering() => m_heatLevel > 0;


        public void Draw(Camera camera, int drawOrder) {
            if (IsPowering() && DrawingUtils.IsVisible(m_subsystemTerrain, camera, new Vector3(m_componentBlockEntity.Coordinates))) {//绘制旋转风扇
                Vector3 pos = new Vector3(m_componentBlockEntity.Coordinates) + new Vector3(0.5f, 0, 0.5f);
                Matrix matrix = Matrix.CreateTranslation(-0.5f, 0, -0.5f) * Matrix.CreateRotationY((float)((Time.RealTime * 20) % (MathF.PI * 2))) * Matrix.CreateTranslation(pos);
                BlocksManager.DrawMeshBlock(
                    m_primitivesRenderer3D,
                    m_fanMesh,
                    IndustrialModLoader.IETexture,
                    Color.White,
                    1,
                    ref matrix,
                    BlocksManager.m_defaultEnvironmentData
                );
                m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
            }
        }
    }
}